package com.jauto.auto.utils;


import com.jauto.auto.core.Node;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.*;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


/**
 * 〈功能概述〉<br>
 *
 * @className: XmlUtil
 * @package: com.java.auto.utils
 * @author: zhangRenHuo
 * @date: 2020/8/5 11:28
 */
public class XmlUtil extends DefaultHandler {

    // 所以node节点
    private NodeList nodeList;
    private List<Element> elements;
    private DocumentBuilderFactory bbf;
    private DocumentBuilder builder;
    private Document doc;
    private String deviceCode;


    public XmlUtil(String path,String deviceCode){
        this.deviceCode = deviceCode;
        bbf = DocumentBuilderFactory.newInstance();
        try {
            builder = bbf.newDocumentBuilder();
            doc = builder.parse(new File(path));
            Element root = doc.getDocumentElement();
            nodeList= root.getElementsByTagName("node");
            init();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * @Description:
     * 防止临时文件被清空
     * @Author zhangRenHuo
     * @Date 17:48 2020/8/6
     * @return
     **/
    public void reset(String path){
        try {
            doc = builder.parse(new File(path));
        } catch (Exception e) {
            e.printStackTrace();
        }
        Element root = doc.getDocumentElement();
        nodeList= root.getElementsByTagName("node");
        init();
    }

    // 初始化
    private void init(){
        elements = new ArrayList<>();
        for (int i = 0; i <nodeList.getLength(); i++){
            elements.add((Element) nodeList.item(i));
        }
    }

    /*
     * @Description:
     * 根据id查询
     * @Author zhangRenHuo
     * @Date 16:05 2020/8/5
     * @return
     **/
    public XmlUtil findById(String id){
        elements = elements.stream().filter(item-> id .equals(item.getAttribute("resource-id"))).collect(Collectors.toList());
        return this;
    }

    public XmlUtil findByParentAndId(String id){
        elements = elements.stream().filter(item->{
            Element parentNode  = (Element)item.getParentNode();
            String attribute = parentNode.getAttribute("resource-id");
            return attribute.equals(attribute);
        }).collect(Collectors.toList());
        return this;
    }

    /**
     * 查询子集id符合的
     */
    public XmlUtil findByChildAndId(String id){
        elements = elements.stream().filter(item->{
            NodeList childNodes = item.getChildNodes();
            for (int i =0;i<childNodes.getLength();i++){
                Element el = (Element) childNodes.item(i);
                if (el.getAttribute("resource-id").equals(id)){
                    return true;
                }
            }
            return false;
        }).collect(Collectors.toList());
        return this;
    }

    /*
     * @Description:
     * 根据class查询
     * @Author zhangRenHuo
     * @Date 16:07 2020/8/5
     * @return 
     **/
    public XmlUtil findByClassName(String className){
        elements = elements.stream().filter(item-> item.getAttribute("class").equals(className)).collect(Collectors.toList());
        return this;
    }

    public XmlUtil findByParentAndClassName(String className){
        elements = elements.stream().filter(item->{
            Element parentNode  = (Element)item.getParentNode();
            String attribute = parentNode.getAttribute("class");
            return attribute.equals(className);
        }).collect(Collectors.toList());
        return this;
    }

    /**
     * 根据子节点的class查询
     * @param className
     * @return
     */
    public XmlUtil findByChildAndClassName(String className){
        elements = elements.stream().filter(item->{
            NodeList childNodes = item.getChildNodes();
            for (int i =0;i<childNodes.getLength();i++){
                Element el = (Element) childNodes.item(i);
                if (el.getAttribute("class").equals(className)){
                    return true;
                }
            }
            return false;
        }).collect(Collectors.toList());
        return this;
    }

    /*
     * @Description:
     * 根据文本查询 支持正则
     * @Author zhangRenHuo
     * @Date 16:41 2020/8/5
     * @return
     **/
    public XmlUtil findByText(String text){
        elements = elements.stream().filter(item->{
            String attribute = item.getAttribute("text");
            return attribute.equals(text)|| Pattern.matches(text, attribute);
        }).collect(Collectors.toList());
        return this;
    }

    public XmlUtil findByParentAndText(String text){
        elements = elements.stream().filter(item->{
            Element parentNode  = (Element)item.getParentNode();
            String attribute = parentNode.getAttribute("text");
            return attribute.equals(text) || Pattern.matches(text, attribute);
        }).collect(Collectors.toList());
        return this;
    }


    public XmlUtil findByChildAndText(String text){
        elements = elements.stream().filter(item->{
            NodeList childNodes = item.getChildNodes();
            for (int i =0;i<childNodes.getLength();i++){
                Element el = (Element) childNodes.item(i);
                String attribute = el.getAttribute("text");
                if (attribute.equals(text) || Pattern.matches(text, attribute)){
                    return true;
                }
            }
            return false;
        }).collect(Collectors.toList());
        return this;
    }

    /*
     * @Description:
     * 根据描述查询 支持正则
     * @Author zhangRenHuo
     * @Date 16:42 2020/8/5
     * @return
     **/
    public XmlUtil findByDesc(String desc){
        elements = elements.stream().filter(item->{
            String attribute = item.getAttribute("content-desc");
            return attribute.equals(desc) || Pattern.matches(desc, attribute);
        }).collect(Collectors.toList());
        return this;
    }

    public XmlUtil findByParentAndDesc(String desc){
        elements = elements.stream().filter(item->{
            Element parentNode  = (Element)item.getParentNode();
            String attribute = parentNode.getAttribute("content-desc");
            return attribute.equals(desc) || Pattern.matches(desc, attribute);
        }).collect(Collectors.toList());
        return this;
    }

    public XmlUtil findByChildAndDesc(String desc){
        elements = elements.stream().filter(item->{
            NodeList childNodes = item.getChildNodes();
            for (int i =0;i<childNodes.getLength();i++){
                Element el = (Element) childNodes.item(i);
                String attribute = el.getAttribute("content-desc");
                if (attribute.equals(desc) || Pattern.matches(desc, attribute)){
                    return true;
                }
            }
            return false;
        }).collect(Collectors.toList());
        return this;
    }

    public XmlUtil findByChildNum(Integer num){
        elements = elements.stream().filter(item->{
            NodeList childNodes = item.getChildNodes();
            return childNodes.getLength() == num;
        }).collect(Collectors.toList());
        return this;
    }

    /*
     * @Description:
     * 得到子集
     * @Author zhangRenHuo
     * @Date 17:25 2020/8/6
     * @return 
     **/
    public XmlUtil getChild(){
        elements = elements.stream().map(item->{
            ArrayList<Element> elements = new ArrayList<>();
            NodeList childNodes = item.getChildNodes();
            for (int i = 0;i < childNodes.getLength(); i++){
                Element element = (Element)childNodes.item(i);
                elements.add(element);
            }
            return elements;
        }).flatMap(item->item.stream()).collect(Collectors.toList());
        return this;
    }

    /*
     * @Description:
     * 获取元素节点
     * @Author zhangRenHuo
     * @Date 16:05 2020/8/5
     * @return
     **/
    public List<Node> getNodes(){
        ArrayList<Node> nodes = new ArrayList<>();
        elements.stream().forEach(item->{
            Node node = new Node();
            node.setDeviceCode(deviceCode);
            node.setText(item.getAttribute("text"));
            node.setResourceId(item.getAttribute("resource-id"));
            node.setClassName(item.getAttribute("class"));
            node.setContentDesc(item.getAttribute("content-desc"));
            node.setCheckable(item.getAttribute("checkable"));
            node.setChecked(item.getAttribute("checked"));
            node.setClickable(item.getAttribute("clickable"));
            node.setBounds(item.getAttribute("bounds"));
            // 将节点的xy坐标储存用于点击
            centerXY(node,item.getAttribute("bounds"));
            nodes.add(node);
        });
        return nodes;
    }

    private void centerXY(Node node,String bounds){
        Pattern p = Pattern.compile("\\d{1,4}");
        Matcher matcher = p.matcher(bounds);
        ArrayList<Integer> list = new ArrayList<>();
        while (matcher.find()) {
            list.add(Integer.parseInt(matcher.group(0)));
        }
        if(list.size() == 4){
            node.setCenterX((list.get(0)+list.get(2))/2);
            node.setCenterY((list.get(1)+list.get(3))/2);
        }
    }

    public List<Element> getElements() {
        return elements;
    }

}
